#include <p24fj16ga002.h>
#include <Generic.h>

#include <stdlib.h>

#ifndef _RS485_H_
#define _RS485_H_
#define  __CRC__
#include <Rs485.h>
#endif

#include <string.h>


WORD HD_CRC_Check(const BYTE* data, WORD pk_size)
{
  BOOL is_odd;
  BYTE i;
  WORD cr;
  volatile BYTE *p;

  p = (volatile BYTE *)&CRCDAT; 
  CRCXOR = 0x1021;  // Polynomial (16, 12, 5, 1)
  CRCCON = 0x000F;  // Length
  CRCWDAT = 0;      // Init. value
  
  is_odd = FALSE;
  if ((pk_size % 2) != 0)
  {
     is_odd = TRUE;
     pk_size--;  // Make the byte count an even number
  }

  // Send EVEN number of bytes to CRC engine
  do
  {              
     while (CRCCONbits.CRCFUL != TRUE && pk_size >0)
     {
        *p = *data++;
        pk_size--;
     }
     if (pk_size == 0)
     {
        break;
     }
     else if (CRCCONbits.CRCFUL == TRUE)
     {
        CRCCONbits.CRCGO = TRUE;      
        while (CRCCONbits.CRCMPT != TRUE)
           continue;
        CRCCONbits.CRCGO = FALSE;
        Nop();
        Nop();
     }
  } while (pk_size > 0); 
 
  if (is_odd == TRUE)
  {
     *p = *data;
     *p = 0;  // Padded with a zero
     CRCCONbits.CRCGO = TRUE;      
     while (CRCCONbits.CRCMPT != TRUE)
        continue;
     CRCCONbits.CRCGO = FALSE;      
  
     // *** Suggested by a Microchip CRC expert ***
     // Manually shift the last byte if the total
     // byte count is odd.
     for (i = 0; i < 8; i ++)
     {
       cr = CRCWDAT & 0x8000;
       CRCWDAT <<= 1;
       if (cr != 0)
          CRCWDAT ^= 0x1021;
     }
  }  
  else
  {      
     CRCDAT=0x0000;
     CRCCONbits.CRCGO = TRUE;      
     while (CRCCONbits.CRCMPT != TRUE)
        continue;
     CRCCONbits.CRCGO = FALSE;      
     Nop();
     Nop();
  }

  return CRCWDAT;
}


